package com.nft.service.school.util;

import java.io.*;
import java.util.*;

import com.alibaba.fastjson.JSONException;
import com.nft.service.school.dto.BookContentDto;
import com.nft.service.school.dto.SubBookContentDto;
import com.nft.utils.common.UUIDgen;
import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.pdfbox.io.RandomAccessBufferedFileInputStream;
import org.apache.pdfbox.io.RandomAccessRead;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

public class ParsePdfContent {
    public static String reader(String filePath) {
        String jsonStr = "";
        try {
            File file = new File(filePath);
            if (file.isFile() && file.exists()) {
                InputStreamReader read = new InputStreamReader(new FileInputStream(file), "UTF-8");
                BufferedReader bufferedReader = new BufferedReader(read);
                String line = null;
                while ((line = bufferedReader.readLine()) != null) {
                    jsonStr += line;
                }
            }
        } catch (UnsupportedEncodingException | FileNotFoundException e) {
            System.out.println("Cannot find the file specified!");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("Error reading file content!");
            e.printStackTrace();
        }
        return jsonStr;
    }

    public static List<String> processTitle(String txtStr, String key) {
        String[] titleAry = txtStr.split(key);
        List<String> titleList = new ArrayList<>();
        for (String title:titleAry) {
            if (title.indexOf("##")>0&&!titleList.contains(key+title.split("##")[0])) {
                titleList.add(key+title.split("##")[0]);
                System.out.println(key+title.split("##")[0]);
            }
        }
        return titleList;
    }

    public static List<BookContentDto> processSubTitle1(File file, String txtStr, String key, String detailKey) {
        String[] titleAry = txtStr.split(key);
        List<BookContentDto> contentRtnList = new ArrayList<>();
        List<String> titleListY = new ArrayList<>();
        List<String> titleList = new ArrayList<>();
        for (String title:titleAry) {
            if (title.indexOf("##")>0&&title.indexOf(")")>0&&!titleListY.contains(title.split("##")[0])) {
                titleListY.add(title.split("##")[0]);
            }
        }
        for (String title:titleListY) {
            String titleJz = title.replaceAll("\\)","").replaceAll("!","");
            if (!titleList.contains(titleJz)) {
                boolean canAdd = true;
                for (String titleJzSub:titleList) {
                    if (titleJz.indexOf(titleJzSub)>=0&&titleJz.length()>titleJzSub.length()) {
                        canAdd = false;
                    }else if (titleJzSub.indexOf(titleJz)>=0&&titleJzSub.length()>titleJz.length()) {
                        titleList.remove(titleJzSub);
                        titleList.add(titleJz);
                        canAdd = false;
                    }
                }
                if (canAdd) {
                    titleList.add(titleJz);
                }
            }
        }
        int pageNum = 1;
        for (int i = 0; i < titleList.size(); i++) {
            BookContentDto content = new BookContentDto();
            String title = titleList.get(i);
            content.setTitle(title);
            pageNum = ParsePdfContent.getPagnumFromPdf(file, pageNum, title);
            content.setPageNum(pageNum);
            content.setSort(i);
            content.setJxkey(detailKey);
            contentRtnList.add(content);
        }
        return contentRtnList;
    }

    public static List<BookContentDto> processSubTitle2(File file, String txtStr, String key, String detailKey) {
        String[] titleAry = txtStr.split(key);
        List<BookContentDto> contentRtnList = new ArrayList<>();
        List<String> titleList = new ArrayList<>();
        for (String title:titleAry) {
            if (title.indexOf("##")>0&&title.indexOf(")")>0&&!titleList.contains(title.split("##")[0])) {
                String titleC = title.split("##")[0];
                if (!"#".equals(titleC.substring(0,1))) {
                    continue;
                }
                if (titleC.split("#").length>2) {
                    titleC = titleC.split("#")[1];
                }
                if (titleC.split("\\$").length>1) {
                    titleC = titleC.split("\\$")[0];
                }
                if (titleC.split("%").length>1) {
                    titleC = titleC.split("%")[0];
                }
                if (titleC.split("&").length>1) {
                    titleC = titleC.split("&")[0];
                }
                if (titleC.split("'").length>1) {
                    titleC = titleC.split("'")[0];
                }
                if (titleC.split("\\(").length>1) {
                    titleC = titleC.split("\\(")[0];
                }
                if (titleC.split("\\)").length>1) {
                    titleC = titleC.split("\\)")[0];
                }
                if (titleC.split("\\*").length>1) {
                    titleC = titleC.split("\\*")[0];
                }
                if (titleC.split("\\!").length>1) {
                    titleC = titleC.split("\\!")[0];
                }
                titleList.add(titleC);
            }
        }
        int pageNum = 1;
        for (int i = 0; i < titleList.size(); i++) {
            BookContentDto content = new BookContentDto();
            String title = titleList.get(i);
            title = title.replaceAll("#","")
                    .replaceAll("\\$","")
                    .replaceAll("%","")
                    .replaceAll("&","")
                    .replaceAll("'","")
                    .replaceAll("\\(","")
                    .replaceAll("\\)","")
                    .replaceAll("\\*","")
                    .replaceAll("\\!","");
            content.setTitle(title);
            pageNum = ParsePdfContent.getPagnumFromPdf(file, pageNum, title);
            content.setPageNum(pageNum);
            content.setSort(i);
            content.setJxkey(detailKey);
            contentRtnList.add(content);
        }
        return contentRtnList;
    }

    public static List<BookContentDto> processContent(File file, List<String> titleList, String txtStr, String key, String detailKey) {
        String[] unitAry = txtStr.split(key);
        Map<Integer, List<String>> contentMap = new HashMap<>();
        List<String> unitList = new ArrayList<>();
        int num = 0;
        for (String unit:unitAry) {
            if (unit.substring(unit.length()-2).indexOf("第")>=0) {
                if ("第一".equals(unit.substring(unit.length()-2))) {
                    num ++;
                    unitList = new ArrayList<>();
                }
                unitList.add(unit.substring(unit.length()-2)+key);
                contentMap.put(num-1, unitList);
                System.out.println(num+"---"+unitList.size()+"---"+unit.substring(unit.length()-2));
            }
        }
        List<BookContentDto> contentRtnList = new ArrayList<>();
        Set<Integer> keySet = contentMap.keySet();
        Object[] ary = keySet.toArray();
        Arrays.sort(ary);
        int pageNum = 1;
        for (int i = 0; i < ary.length; i++) {
            BookContentDto content = new BookContentDto();
            content.setTitle(titleList.get(Integer.valueOf(ary[i].toString())));
            List<String> keyList = contentMap.get(Integer.valueOf(ary[i].toString()));
            List<SubBookContentDto> subTitleList = new ArrayList<>();
            for (int ii = 0; ii<keyList.size(); ii++) {
                String keyStr = keyList.get(ii);
                pageNum = ParsePdfContent.getPagnumFromPdf(file, pageNum, keyStr);
                SubBookContentDto subContent = new SubBookContentDto();
                subContent.setTitle(keyStr);
                subContent.setPageNum(pageNum);
                subContent.setSort(ii);
                subTitleList.add(subContent);
            }
            content.setSubTitleList(subTitleList);
            content.setSort(i);
            content.setJxkey(detailKey);
            contentRtnList.add(content);
        }
        return contentRtnList;
    }

    public static int getPagnumFromPdf(File file, int startPageNum, String keyText) {
        int pagenum = 0;
        if(file.exists()) {
            PDDocument doc = null;
            try {
                FileInputStream in = new FileInputStream(file);
                RandomAccessRead randomAccessRead = new RandomAccessBufferedFileInputStream(in);
                PDFParser parser = new PDFParser(randomAccessRead);
                parser.parse();
                doc = parser.getPDDocument();
                PDFTextStripper textStripper = new PDFTextStripper();
                for (int i = startPageNum; i <= doc.getNumberOfPages(); i++) {
                    textStripper.setStartPage(i);
                    textStripper.setEndPage(i);
                    // 一次输出多个页时，按顺序输出
                    textStripper.setSortByPosition(true);
                    String s = textStripper.getText(doc);
                    System.out.println("keyText：" + keyText);
                    if (s.indexOf(keyText)>=0) {
                        System.out.println("当前页：" + i);
                        System.out.println("输出内容："+keyText);
                        pagenum = i;
                        return pagenum;
                    }
                }
            }catch (IOException e) {
            }finally {
                if (null!=doc) {
                    try {
                        doc.close();
                    }catch (IOException ioe) {}
                }
            }
        }
        return pagenum;
    }

    public static boolean generateBase64StringToFile(String fileBase64, String fileFilePath){
        if (fileBase64 == null) //文件base64位数据为空
            return false;
        try {
            //Base64解码
            byte[] b = org.apache.commons.codec.binary.Base64.decodeBase64(fileBase64);
            for(int i=0;i<b.length;++i)
            {
                if(b[i]<0)
                {//调整异常数据
                    b[i]+=256;
                }
            }
            //生成文件
            OutputStream out = new FileOutputStream(fileFilePath);
            out.write(b);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static String execCurl(String URL, String params) {
        StringEntity entity = new StringEntity(params, ContentType.APPLICATION_JSON);
        HttpClient httpClient = HttpClientBuilder.create().build();
        HttpPost request = new HttpPost(URL);
        request.setEntity(entity);
        HttpResponse response = null;
        try {
            response = httpClient.execute(request);
            if (response.getStatusLine().getStatusCode()==200) {
                String responseBody = EntityUtils.toString(response.getEntity());
                JSONObject json = JSON.parseObject(responseBody);
                System.out.println(json.get("data"));
                return json.get("data").toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
    private static String getJsonContent(String imgPath, String message) throws JSONException {
        JSONObject json = new JSONObject();
        String[] imgAry = {imgPath};
        String[] emptyAry = {};
        json.put("uuid", "34324141");
        json.put("img_paths", imgAry );
        json.put("prompt", message);
        json.put("user_input", "");
        json.put("history", emptyAry);
        json.put("is_image", "true");
        return json.toString();
    }
    public static String OCR(String fileBase64, String uploadpath, String fileSuffix, String message) {
        String filePath = uploadpath+File.separator+ UUIDgen.getUUID()+fileSuffix;
        generateBase64StringToFile(fileBase64, filePath);
        File imageFile = new File(filePath);
        System.out.println("filePath:"+filePath);
        try {
            String param = getJsonContent(filePath, message);
            String rtn = execCurl("http://localhost:8088/ai_server", param);
            return rtn;
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            imageFile.delete();
        }
        return "";
    }

    public static String OCR1(String fileBase64, String libPath, String wordLib, String uploadpath, String fileSuffix) {
        String filePath = uploadpath+File.separator+ UUIDgen.getUUID()+fileSuffix;
        generateBase64StringToFile(fileBase64, filePath);
        File imageFile = new File(filePath);
        ITesseract tessreact = new Tesseract();
        tessreact.setLanguage(wordLib);
        tessreact.setDatapath(libPath);
        tessreact.setOcrEngineMode(3);
        tessreact.setTessVariable("user_defined_dpi", "300");
        String result = "";
        try {
            result = tessreact.doOCR(imageFile);
        }catch (TesseractException e) {
            e.printStackTrace();
        }finally {
            imageFile.delete();
        }
        return result;
    }

    public static String OCR2(String filePath, String libPath, String wordLib, String uploadpath, String fileSuffix) {
        File imageFile = new File(filePath);
        Tesseract tessreact = new Tesseract();
        tessreact.setDatapath(libPath);
        tessreact.setTessVariable("user_defined_dpi", "300");
        tessreact.setLanguage(wordLib);
        String result = "";
        try {
            System.out.println("filePath:"+filePath);
            System.out.println("imageFile:"+imageFile.getPath());
            result = tessreact.doOCR(imageFile);
        }catch (TesseractException e) {
            e.printStackTrace();
        }finally {
            imageFile.delete();
        }
        return result;
    }

    private static MultipartFile getMultipartFile(File file){
        FileInputStream fileInputStream = null;
        MultipartFile multipartFile = null;
        try {
            fileInputStream = new FileInputStream(file);
            multipartFile = new MockMultipartFile(file.getName(),file.getName(),
                    ContentType.APPLICATION_OCTET_STREAM.toString(),fileInputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return multipartFile;
    }

    public static void main(String[] args) {
        //ParsePdfContent.tqPdfDataToTxt("D:\\tempbook\\2_中考历史必考考点背记手册.pdf", "D:\\tempbook\\2_中考历史必考考点背记手册.txt");
        String uploadPath = "D:\\tempbook\\";
        File yfile = new File(uploadPath+"q1.png");
        MultipartFile file = getMultipartFile(yfile);
        String fileSuffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")).toLowerCase();
        try {
            String fileBase64 = Base64Util.getInstance().encode(file.getBytes());
            System.out.println(fileBase64);
            String result = ParsePdfContent.OCR(fileBase64, uploadPath, fileSuffix, "");
            System.out.println("结果："+result);
        }catch (IOException e) {}
        /*String fileName = "D:\\tempbook\\中考道德与法治一轮复习 知识点整理.txt";
        String txtStr = reader(fileName);
        fileName = fileName.replaceAll(".txt",".pdf");
        File file = new File(fileName);
        if (!"".equals(txtStr)) {*/
            /*List<String> titleList = processTitle(txtStr, "模块");
            System.out.println(titleList);
            List<BookContentDto> contentRtnList = processContent(file, titleList, txtStr, "单元");
            System.out.println(contentRtnList);*/

            /*List<BookContentDto> titleList = processSubTitle1(file, txtStr, "学习主题");
            System.out.println(titleList);
            List<BookContentDto> contentRtnListY = processSubTitle2(file, txtStr, "#课时#");
            System.out.println(contentRtnListY);*/

            /*String[] jxkeySAry = "学习主题,#课时#".split(",");
            System.out.println(jxkeySAry);
            List<BookContentDto> contentRtnList = new ArrayList<>();
            if (jxkeySAry.length>1) {
                contentRtnList = ParsePdfContent.processSubTitle1(file, txtStr, jxkeySAry[0]);
                List<BookContentDto> contentRtnListN = ParsePdfContent.processSubTitle2(file, txtStr, jxkeySAry[1]);
                contentRtnList.addAll(contentRtnListN);
            }
        }else {
            System.out.println("Read the content is empty!");
        }*/
    }
}
